#include "PrecisionTimer.h"
#include "Config.h"

PrecisionTimer::PrecisionTimer() 
    : mSecondsPerCount( 0.0), mDeltaTime(-1.0), mBaseTime( 0),
    mPausedTime( 0), mPrevTime( 0), mCurrTime( 0), mStopped( false) { 
        __int64 countsPerSec;
        QueryPerformanceFrequency(( LARGE_INTEGER*)& countsPerSec);
        mSecondsPerCount = 1.0 / (double) countsPerSec;
}

void PrecisionTimer::Tick() {
    if(mStopped) {
        mDeltaTime = 0.0;
        return;
    }

    //Get the time this frame
    __int64 currTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
    mCurrTime = currTime;

    //time difference between this frame and the previous
    mDeltaTime = (mCurrTime - mPrevTime)*mSecondsPerCount;

    //Prepare for the next frame
    mPrevTime = mCurrTime;

    //Make mDeltaTime nonnegative. Can become negative if the processor goes
    //into a power saving mode.
    if(mDeltaTime < 0.0) {
        mDeltaTime = 0.0;
    }
}

float PrecisionTimer::DeltaTime() const {
    return (float)mDeltaTime;
}

void PrecisionTimer::Reset() {
    __int64 currTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);

    mBaseTime = currTime;
    mPrevTime = currTime;
    mStopTime = 0;
    mStopped = false;
}

void PrecisionTimer::Start() {
    __int64 startTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&startTime);

    //if we are resuming the timer from a stopped state
    if(mStopped) {
        mPausedTime += startTime - mStopTime;
        mPrevTime = startTime;
        mStopTime = 0;
        mStopped = false;
    }
}

void PrecisionTimer::Stop() {
    if(!mStopped) {
        __int64 currTime;
        QueryPerformanceCounter((LARGE_INTEGER*)&currTime);

        mStopTime = currTime;
        mStopped = true;
    }
}

float PrecisionTimer::TotalTime()const {
    if(mStopped) {
        return (float)(((mStopTime - mPausedTime)-mBaseTime)*mSecondsPerCount);
    } else {
        return (float)(((mCurrTime - mPausedTime)-mBaseTime)*mSecondsPerCount);
    }
}